/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.functors;

import org.jetbrains.annotations.NotNull;

public abstract class NullaryReturningFunctorBoolean extends NullaryReturningFunctor<Boolean>
{
	@NotNull
	public final NullaryReturningFunctorBoolean not()
	{
		return not(this);
	}

	@NotNull
	public final NullaryReturningFunctorBoolean and(final @NotNull NullaryReturningFunctor<Boolean>... functors)
	{
		return and(this, functors);
	}

	@NotNull
	public final NullaryReturningFunctorBoolean or(final @NotNull NullaryReturningFunctor<Boolean>... functors)
	{
		return or(this, functors);
	}

	@NotNull
	public static NullaryReturningFunctorBoolean toNullaryReturningFunctorBoolean(final @NotNull NullaryReturningFunctor<Boolean> functor)
	{
		if (functor instanceof NullaryReturningFunctorBoolean)
		{
			return (NullaryReturningFunctorBoolean) functor;
		}
		return new NullaryReturningFunctorBoolean()
		{
			@NotNull
			public Boolean closure()
			{
				return functor.closure();
			}
		};
	}

	@NotNull
	public static NullaryReturningFunctorBoolean not(final @NotNull NullaryReturningFunctor<Boolean> that)
	{
		return new NullaryReturningFunctorBoolean()
		{
			@NotNull
			public Boolean closure()
			{
				return that.closure().not();
			}
		};
	}

	@NotNull
	public static NullaryReturningFunctorBoolean and(final @NotNull NullaryReturningFunctor<Boolean> left, final @NotNull NullaryReturningFunctor<Boolean>... functors)
	{
		return new NullaryReturningFunctorBoolean()
		{
			@NotNull
			public Boolean closure()
			{
				final Boolean result = left.closure();
				if (result.isFalse())
				{
					return result;
				}
				for (NullaryReturningFunctor<Boolean> functor : functors)
				{
					final Boolean aBoolean = functor.closure();
					if (aBoolean.isFalse())
					{
						return result;
					}
				}
				return Boolean.True;
			}
		};
	}

	@NotNull
	public static NullaryReturningFunctorBoolean or(final @NotNull NullaryReturningFunctor<Boolean> left, final @NotNull NullaryReturningFunctor<Boolean>... functors)
	{
		return new NullaryReturningFunctorBoolean()
		{
			@NotNull
			public Boolean closure()
			{
				Boolean result = left.closure();
				for (NullaryReturningFunctor<Boolean> functor : functors)
				{
					final Boolean that = functor.closure();
					result = result.or(that);
				}
				return result;
			}
		};
	}
}
